﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

using Microsoft.AspNetCore.Http;
using Microsoft.VisualBasic;

namespace zijian666.WebApi
{
    public partial class DefaultResult
    {
        /// <summary>
        /// 默认全局返回值格式器
        /// </summary>
        public class Formatter : IResultFormatter
        {
            private readonly HttpContextAccessor _httpContext;
            /// <summary>
            /// 默认构造函数
            /// </summary>
            /// <param name="httpContext"></param>
            /// <exception cref="ArgumentNullException"></exception>
            public Formatter(HttpContextAccessor httpContext) => _httpContext = httpContext ?? throw new ArgumentNullException(nameof(httpContext));

            /// <inheritdoc/>
            public object Empty() => (Code: 200, Message: "ok");

            /// <summary>
            /// 请求Id
            /// </summary>
            public string RequestId => _httpContext.HttpContext?.TraceIdentifier ?? "none";

            /// <inheritdoc/>
            public object Ok(object? data, string? message)
                => new DefaultResult<object>(RequestId) { Data = data, Message = message ?? "ok" };


            /// <inheritdoc/>
            public object Error(Exception ex, string? message)
            {
                if (ex is null)
                {
                    throw new ArgumentNullException(nameof(ex));
                }

                return new DefaultResult(RequestId) { Exceptions = ParseExceptionInfo(ex), Code = ex.HResult < -2100000000 ? 500 : ex.HResult, Subcode = "error", Message = message ?? ex.Message };
            }

            /// <inheritdoc/>
            public object Fail(int httpStatusCode, string? message)
                => new DefaultResult(RequestId) { Code = httpStatusCode, Subcode = "fail", Message = message ?? "fail" };

            /// <inheritdoc/>
            public object Fail(int httpStatusCode, string? subCode, string? message)
                => new DefaultResult(RequestId) { Code = httpStatusCode, Subcode = subCode ?? "fail", Message = message ?? "fail" };

            /// <inheritdoc/>
            public object Custom(int httpStatusCode, string? subCode, object? data, string? message)
                => new DefaultResult(RequestId) { Code = httpStatusCode, Subcode = subCode ?? "ok", Message = message ?? "ok" };

            /// <inheritdoc/>
            public Type GetResultType(Type type)
{
                if (type is null || type == typeof(void) )
                {
                    return typeof(DefaultResult);
                }
                return typeof(DefaultResult<>).MakeGenericType(type);
            }


            /// <summary>
            /// 解析异常类 <seealso cref="Exception"/>
            /// </summary>
            public static IList<ExceptionInfo> ParseExceptionInfo(Exception ex)
            {
                var list = new List<ExceptionInfo>();
                var e = ex;
                while (e is not null)
                {
                    list.Add(new(e.Message, e.StackTrace ?? ""));
                    e = e.InnerException;
                }
                return list;
            }
        }
    }
}
